package common

import (
	"gitee.com/kinwyb/conv"
	"math"
	"strconv"
)

type RedisScoreValue struct {
	value string
	score float64
}

func NewRedisScoreValue(value string, score float64) *RedisScoreValue {
	return &RedisScoreValue{
		value: value,
		score: score,
	}
}

func (r *RedisScoreValue) Set(value string, score float64) {
	r.value = value
	r.score = score
}

func (r *RedisScoreValue) Value() string {
	return r.value
}

func (r *RedisScoreValue) Score() float64 {
	return r.score
}

type RedisSortSet struct {
	redis *RedisUtil
	key   string //按键值
}

func NewRedisSortSet(redis *RedisUtil, key string) *RedisSortSet {
	return &RedisSortSet{
		redis: redis,
		key:   key,
	}
}

// 新增内容
func (r *RedisSortSet) Add(value string, score float64) int64 {
	ret, err := r.redis.ZADD(r.key, score, value)
	if err != nil {
		return -1
	}
	return ret
}

// 按小score更新
func (r *RedisSortSet) UpdateValueWithMinScore(value string, score float64) int64 {
	oldScore, err := r.redis.ZSCORE(r.key, value)
	if err != nil {
		oldScore = math.MaxFloat64
	}
	score = math.Min(oldScore, score)
	result, err := r.redis.ZADD(r.key, score, value)
	if err != nil {
		return -1
	}
	return result
}

// 获取分数值
func (r *RedisSortSet) ValueScore(value string) float64 {
	ret, _ := r.redis.ZSCORE(r.key, value)
	return ret
}

// 为成员score增加值
func (r *RedisSortSet) ScoreIncry(value string, num int64) bool {
	ret, _ := r.redis.ZINCRBY(r.key, num, value)
	return ret == 1
}

// 按大score
func (r *RedisSortSet) UpdateValueWithMaxScore(value string, score float64) int64 {
	oldScore, err := r.redis.ZSCORE(r.key, value)
	if err != nil {
		oldScore = math.SmallestNonzeroFloat64
	}
	score = math.Max(oldScore, score)
	ret, err := r.redis.ZADD(r.key, score, value)
	if err != nil {
		return -1
	}
	return ret
}

// 大小
func (r *RedisSortSet) Size() int64 {
	ret, err := r.redis.ZCARD(r.key)
	if err != nil {
		return 0
	}
	return conv.ToInt64(ret)
}

// 获取最小值
func (r *RedisSortSet) MinScoreValue() string {
	rets, err := r.redis.ZRANGE(r.key, 0, 0, false)
	if err != nil || len(rets) < 1 {
		return ""
	}
	return rets[0]
}

// 按最小值排序
func (r *RedisSortSet) MinScoreValues() ([]*RedisScoreValue, error) {
	values, err := r.redis.ZRANGE(r.key, 0, -1, true)
	if err != nil {
		return nil, err
	}
	var ret []*RedisScoreValue
	for i, v := range values {
		if i%2 != 1 {
			continue
		}
		score, _ := strconv.ParseFloat(v, 64)
		ret = append(ret, NewRedisScoreValue(values[i-1], score))
	}
	return ret, nil
}

// 获取最大值
func (r *RedisSortSet) MaxScoreValue() string {
	ret, err := r.redis.ZREVRANGE(r.key, 0, 0, false)
	if err != nil || len(ret) < 1 {
		return ""
	}
	return ret[0]
}

// 按最大值排序
func (r *RedisSortSet) MaxScoreValues() ([]*RedisScoreValue, error) {
	values, err := r.redis.ZREVRANGE(r.key, 0, -1, true)
	if err != nil {
		return nil, err
	}
	var ret []*RedisScoreValue
	for i, v := range values {
		if i%2 != 1 {
			continue
		}
		score, _ := strconv.ParseFloat(v, 64)
		ret = append(ret, NewRedisScoreValue(values[i-1], score))
	}
	return ret, nil
}

// 按从大到小排序取排序值
func (r *RedisSortSet) IndexByMaxSort(value string) int64 {
	ret, err := r.redis.ZREVRANK(r.key, value)
	if err != nil {
		return -1
	}
	return ret

}

// 按从小到大排序取排序值
func (r *RedisSortSet) IndexByMinSort(value string) int64 {
	ret, err := r.redis.ZRANK(r.key, value)
	if err != nil {
		return -1
	}
	return ret
}

// 移除
func (r *RedisSortSet) RemoveValue(value string) error {
	_, err := r.redis.ZREM(r.key, value)
	return err
}
